import { useMutation } from '@tanstack/react-query';
import { App } from 'antd';
import { useNavigate } from 'react-router-dom';
import { create } from 'zustand';

import operationService from '@/api/services/security/operationService';
import userService, { SignInReq } from '@/api/services/security/userService';
import { getItem, removeItem, setItem } from '@/utils/storage';

import { CascaderOption, Operation, UserInfo, UserToken } from '#/entity';
import { StorageEnum } from '#/enum';

const { VITE_APP_HOMEPAGE: HOMEPAGE } = import.meta.env;

type UserStore = {
  userInfo: Partial<UserInfo>;
  userToken: UserToken;
  operation: CascaderOption[];
  // 使用 actions 命名空间来存放所有的 action
  actions: {
    setOperation: (operation: CascaderOption[]) => void;
    setUserInfo: (userInfo: UserInfo) => void;
    setUserToken: (token: UserToken) => void;
    setDicts: () => void;
    clearUserInfoAndToken: () => void;
    clearRegion: () => void;
    clearMenu: () => void;
  };
};

const useUserStore = create<UserStore>((set) => ({
  userInfo: getItem<UserInfo>(StorageEnum.User) || {},
  userToken: getItem<UserToken>(StorageEnum.Token) || {},
  operation: getItem<CascaderOption[]>(StorageEnum.Operation) || [],
  actions: {
    setUserInfo: (userInfo) => {
      set({ userInfo });
      setItem(StorageEnum.User, userInfo);
    },
    setDicts: () => {},
    setUserToken: (userToken: UserToken) => {
      set({ userToken });
      setItem(StorageEnum.Token, userToken);
    },
    setOperation: (operation: CascaderOption[]) => {
      set({ operation });
      setItem(StorageEnum.Operation, operation);
    },
    clearUserInfoAndToken() {
      set({ userInfo: {}, userToken: {} });
      removeItem(StorageEnum.User);
      removeItem(StorageEnum.Token);
      removeItem(StorageEnum.Operation);
    },
    clearMenu() {
      removeItem(StorageEnum.User);
    },
    clearRegion() {
      removeItem(StorageEnum.Regions);
    },
  },
}));

export const useUserInfo = () => useUserStore((state) => state.userInfo);
export const useUserToken = () => useUserStore((state) => state.userToken);
export const useUserPermission = () => useUserStore((state) => state.userInfo.permissions);
export const useUserActions = () => useUserStore((state) => state.actions);
export const useOperation = () => useUserStore((state) => state.operation);

const operationToOption = (operations: any): CascaderOption[] => {
  const options: CascaderOption[] = [];
  Object.keys(operations).map((key) => {
    const entityMapping = operations[key];
    const moduleName = entityMapping[Object.keys(entityMapping)[0]][0].entity.module.name;
    const moduleOption: CascaderOption = {
      value: key,
      isLeaf: false,
      label: moduleName,
    };
    const entityList: CascaderOption[] = [];
    Object.keys(entityMapping).map((entity) => {
      const list: Operation[] = entityMapping[entity];
      const entityOption: CascaderOption = {
        label: list[0].entity.name,
        value: entity,
        isLeaf: false,
      };
      const operationList: CascaderOption[] = [];
      list.map((item) => {
        const operationOption: CascaderOption = {
          value: item.code,
          isLeaf: true,
          label: item.name,
        };
        operationList.push(operationOption);
        return item;
      });
      entityOption.children = operationList;
      entityList.push(entityOption);
      return entity;
    });
    moduleOption.children = entityList;
    options.push(moduleOption);
    return key;
  });
  return options;
};
export const useSignIn = () => {
  const navigate = useNavigate();
  const { message } = App.useApp();
  const { setUserToken, setUserInfo, setOperation } = useUserActions();

  const signInMutation = useMutation({
    mutationFn: userService.signin,
  });
  const menuMutation = useMutation({
    mutationFn: userService.menuPermissions,
  });
  const operationMutation = useMutation({
    mutationFn: operationService.operationGroup,
  });
  const rulesMutation = useMutation({
    mutationFn: userService.hasRules,
  });
  return async (param: SignInReq) => {
    try {
      param.app = import.meta.env.VITE_APP_SIGNIN_NAME;

      const user = await signInMutation.mutateAsync(param);
      user.permissions = await menuMutation.mutateAsync();
      const accessToken = user.id;
      const refreshToken = user.id;
      const operations = await operationMutation.mutateAsync({});
      const rules = await rulesMutation.mutateAsync();
      setItem(StorageEnum.Rules, rules);
      setOperation(operationToOption(operations));
      setUserToken({ accessToken, refreshToken });

      setUserInfo(user);
      navigate(HOMEPAGE, { replace: true });
    } catch (err: any) {
      message.warning({
        content: err.message,
        duration: 3,
      });
      throw err;
    }
  };
};

export default useUserStore;
